﻿using AVCUMPlatform.DingTalkService.Interface;
using AVCUMPlatform.DingTalkService.Model;
using AVCUMPlatform.Entities;
using AVCUMPlatform.HelperLibrary;
using HelperLibrary;
using Newtonsoft.Json;
using System.Reflection;
using Text = AVCUMPlatform.DingTalkService.Model.Text;

namespace AVCUMPlatform.DingTalkService.Service
{
    public class DingTalkService : IDingPlatformApiHelper
    {
        /// <summary>
        /// appid
        /// </summary>
        private string _appid { get; set; }
        /// <summary>
        /// appSecret
        /// </summary>
        private string _appSecret { get; set; }
        /// <summary>
        /// 客户端地址
        /// </summary>
        private string _clientHost { get; set; }
        private Int64 _agentId { get; set; }
        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="appSecret"></param>
        public DingTalkService(string appid, string appSecret, string clientHost, Int64 agentId)
        {
            _appid = appid;
            _appSecret = appSecret;
            _clientHost = clientHost;
            _agentId = agentId;
        }

        /// <summary>
        /// hosturl
        /// </summary>
        public static string host = string.Empty;

        //public string GetUserId(string code)
        //{
        //    string token = DingTalkToken.GetInstance(_appid, _appSecret).AccessToken;
        //    string url = $"{host}/user/getuserinfo?access_token={token}&code={code}";
        //    DingTalkUser result = HTTPHelper.Get<DingTalkUser>(url);
        //    return result.userid;
        //}
        /// <summary>
        /// 获取部门
        /// </summary>
        /// <returns></returns>
        public List<Department> GetDepartment()
        {
            string token = DingTalkToken.GetInstance(_appid, _appSecret).AccessToken;
            string url = $"https://oapi.dingtalk.com/department/list?access_token={token}";
            DingDepartment result = HTTPHelper.Get<DingDepartment>(url);
            List<Department> departmentList = result.department;
            return departmentList;
        }
        public List<DingTalkUser> GetAllUsers() 
        {
            var allDepList = GetDepartment();
            //获取钉钉所有的部门包含子部门
            var containsChildAllDepList = new List<string>();
            foreach (var parentDepId in allDepList)
            {
                var childDepIdList = new List<string>();
                GetDepIdChildList(parentDepId.id.ToString(), allDepList, childDepIdList);
                containsChildAllDepList.AddRange(childDepIdList);
            }
            containsChildAllDepList.AddRange(allDepList.Select(x => x.id.ToString()).ToList());
            //获取钉钉所有部门对应的用户
            var allDingTalkUserList = GetUser(containsChildAllDepList);
            return allDingTalkUserList;
        }
        public List<DingTalkUser> GetUser(List<string> departmentIdList)
        {
            string token = DingTalkToken.GetInstance(_appid, _appSecret).AccessToken;
            string url = $"https://oapi.dingtalk.com/topapi/v2/user/list?access_token={token}";
            var alluserList = new List<DingTalkUser>();
            foreach (var departmentId in departmentIdList)
            {
                var data = new
                {
                    cursor = "0",
                    contain_access_limit = "true",
                    size = "100",
                    order_field = "entry_asc",
                    language = "zh_CN",
                    dept_id = departmentId
                };
                DingRes result = HTTPHelper.Post<DingRes>(url, data);
                List<DingTalkUser> userListBydeptId = result.result.list;
                alluserList.AddRange(userListBydeptId);
            }
            return alluserList.DistinctBy(x => x.userid).ToList();
        }
        private void GetDepIdChildList(string parentId, List<Department> allDepList, List<string> depIds)
        {
            List<Department> children = allDepList.Where(s => s.parentid.ToString() == parentId).ToList();
            if (children.Count == 0)
            {
                return;
            }
            depIds.AddRange(children.Select(x => x.id.ToString()).ToList());
            foreach (Department dept in children)
            {
                GetDepIdChildList(dept.id.ToString(), allDepList, depIds);
            }
        }
        /// <summary>
        /// 需开通qyapi_get_member_by_mobile
        /// </summary>
        /// <param name="mobiles"></param>
        /// <returns></returns>
        public string GetUserId(string mobiles)
        {
            var userIdStr = string.Empty;
            string token = DingTalkToken.GetInstance(_appid, _appSecret).AccessToken;
            if (string.IsNullOrWhiteSpace(mobiles))
            {
                return string.Empty;
            }
            else
            {
                var mobileList = mobiles.Split(",").ToList();
                if (mobileList != null && mobileList.Any())
                {
                    var userIdList = new List<string>();
                    foreach (var mobile in mobileList)
                    {
                        var dingding_userid = CacheHelper.Get<string>($"dingding_userid_{mobile}");
                        if (!string.IsNullOrWhiteSpace(dingding_userid))
                        {
                            userIdList.Add(dingding_userid);
                        }
                        else
                        {
                            string url = $"{host}/user/get_by_mobile?access_token={token}&mobile={mobile}";
                            DingTalkUser result = HTTPHelper.Get<DingTalkUser>(url);
                            if (result != null && !string.IsNullOrWhiteSpace(result.userid))
                            {
                                userIdList.Add(result.userid);
                                CacheHelper.Set($"dingding_userid_{result.userid}", result.userid, TimeSpan.FromDays(30));
                            }
                        }
                    }
                    if (userIdList.Any())
                    {
                        userIdStr = string.Join("|", userIdList);
                    }
                }
            }
            
            return userIdStr;
        }

        //public bool SendToGroupMessage(string msg)
        //{
        //    //消息类型
        //    var msgtype = MsgTypeEnum.text.ToString();

        //    //文本内容
        //    var text = new Text
        //    {
        //        Content = $"RabbitMQ测试:\n{msg}"
        //    };

        //    //指定目标人群
        //    var at = new At()
        //    {
        //        AtMobiles = new List<string>() { "15594180162" },
        //        IsAtAll = false
        //    };
        //    var WebHook_Token = $"{host}/robot/send?access_token=83e9666710720ae9d2374a42d7c10edff87d20717623bb71ada560d00f6af60c";
        //    var response = HTTPHelper.Post<HttpResponseMessage>(WebHook_Token, new { msgtype, text, at });
        //    return response.IsSuccessStatusCode;
        //}

        /// <summary>
        /// 发给指定人通知信息
        /// </summary>
        /// <param name="userPhones">用户手机号（多个逗号隔开）</param>
        /// <param name="userIds">用户手机号（多个逗号隔开）</param>
        /// <param name="content">内容</param>
        /// <returns></returns>
        public DingTalkSendMsg DingSendPersonalRemindMsg(string userPhones, string userIds,string content)
        {
            try
            {
                var DingTalkSend = new DingTalkSend
                {
                    toparty = "",
                    agentid = _agentId,
                    msgtype = "text",
                    text = new Text { Content = content },
                };
                if (!string.IsNullOrWhiteSpace(userIds))
                {
                    var userIdList = userIds.Split(',').ToList();
                    //var allDingTalkUserList = GetAllUsers();
                    //var dingTalkUserIdList = allDingTalkUserList.Where(x => userIdList.Any(y => y == x.job_number)).Select(x => x.userid).ToList();
                    DingTalkSend.touser = string.Join("|", userIdList);
                }
                if (!string.IsNullOrWhiteSpace(userPhones))
                {
                    DingTalkSend.touser = GetUserId(userPhones);
                }

                return SendTemplateMsg(DingTalkSend);
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// 发送机器人消息
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public DingTalkSendMsg SendRobotMsg(Robot data)
        {
            try
            {
                string url = $"{data.Webhook}&{Util.RobotSignAndTimestamp(data.Sign)}";
                var obj = new
                {
                    msgtype = "text",
                    text = new
                    {
                        content = data.Content
                    }
                };
                return HTTPHelper.Post<DingTalkSendMsg>(url, obj);
            }
            catch (Exception)
            {
                throw;
            }
        }
        private DingTalkSendMsg SendTemplateMsg(DingTalkSend data)
        {
            try
            {
                string token = DingTalkToken.GetInstance(_appid, _appSecret).AccessToken;
                string url = $"{host}/message/send?access_token={token}";
                //string url = $"{host}/topapi/message/corpconversation/asyncsend_v2?access_token={token}";
                return HTTPHelper.Post<DingTalkSendMsg>(url, data);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 发送待审批提醒
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="orderId">预约id</param>
        /// <param name="applicantName">eg：张三</param>
        /// <param name="flowName">eg: 重要会议预约</param>
        /// <param name="content">eg: 场地：A01，使用时间：2019-12-23日第五节</param>
        /// <param name="applyTime">2020-12-23 12:23</param>
        /// <returns></returns>
        public DingTalkSendMsg DingSendAuditRemindMsg(string userid, int orderId,
            string applicantName, string flowName, string content, string applyTime)
        {
            try
            {
                DingTalkAsyncSend msgRM = new DingTalkAsyncSend
                {
                    to_all_user = false,
                    userid_list = userid,
                    agent_id = _agentId,
                    msg = new MsgModel
                    {
                        msgtype = "oa",
                        oa = new OAModel
                        {
                            message_url = $"{_clientHost}/pages/approval/details?id={orderId}&type=0&clienttype=2",
                            head = new HeadModel
                            {
                                text = "审批提醒",
                                bgcolor = "FFBBBBBB"
                            },
                            body = new BodyModel
                            {
                                title = $"审批提醒",
                                content = $"【{applicantName}】有一个新的场地预约申请需要您审批",
                                form = new List<KeyValue>
                                {
                                   new  KeyValue{

                                        value = flowName,
                                        key = "审批流程："
                                    },
                                    new  KeyValue{
                                        value = content,
                                        key = "详情："
                                    },
                                   new  KeyValue {
                                        value = applicantName,
                                        key = "申请人："
                                    },
                                    new  KeyValue{
                                        value = applyTime,
                                        key = "申请时间："
                                    },
                                   new  KeyValue {
                                        value = "请尽快处理",
                                        key = "备注："
                                    }
                                }
                            }
                        }

                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }

        /// <summary>
        /// 发送批量待审批提醒
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="orderId">预约id</param>
        /// <param name="batchOrderId"></param>
        /// <param name="applicantName">eg：张三</param>
        /// <param name="flowName">eg: 重要会议预约</param>
        /// <param name="content">eg: 场地：A01，使用时间：2019-12-23日第五节</param>
        /// <param name="applyTime">2020-12-23 12:23</param>
        /// <returns></returns>
        public DingTalkSendMsg DingSendBatchAuditRemindMsg(string userid, int batchOrderId,
            string applicantName, string flowName, string content, string applyTime)
        {
            try
            {
                DingTalkAsyncSend msgRM = new DingTalkAsyncSend
                {
                    to_all_user = false,
                    userid_list = userid,
                    agent_id = _agentId,
                    msg = new MsgModel
                    {
                        msgtype = "oa",
                        oa = new OAModel
                        {
                            message_url = $"{_clientHost}/pages/approval/details?id={batchOrderId}&type=3&clienttype=2",
                            head = new HeadModel
                            {
                                text = "审批提醒",
                                bgcolor = "FFBBBBBB"
                            },
                            body = new BodyModel
                            {
                                title = $"审批提醒",
                                content = $"【{applicantName}】有一个新的批量预约申请需要您审批",
                                form = new List<KeyValue>
                                {
                                   new  KeyValue{

                                        value = flowName,
                                        key = "审批流程："
                                    },
                                    new  KeyValue{
                                        value = content,
                                        key = "详情："
                                    },
                                   new  KeyValue {
                                        value = applicantName,
                                        key = "申请人："
                                    },
                                    new  KeyValue{
                                        value = applyTime,
                                        key = "申请时间："
                                    },
                                   new  KeyValue {
                                        value = "请尽快处理",
                                        key = "备注："
                                    }
                                }
                            }
                        }

                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }

        /// <summary>
        /// 发送审批消息
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="OrderId"></param>
        /// <param name="applicantName"></param>
        /// <param name="flowName"></param>
        /// <param name="content"></param>
        /// <param name="applyTime"></param>
        /// <param name="adjustName"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public DingTalkSendMsg DingSendAdjustAuditRemindMsg(string userid, int OrderId,
          string applicantName, string flowName, string content, string applyTime, string adjustName, int type = 1)
        {
            try
            {
                DingTalkAsyncSend msgRM = new DingTalkAsyncSend
                {
                    to_all_user = false,
                    userid_list = userid,
                    agent_id = _agentId,
                    msg = new MsgModel
                    {
                        msgtype = "oa",
                        oa = new OAModel
                        {
                            message_url = $"{_clientHost}/pages/approval/details?id={OrderId}&type={type}&clienttype=2",
                            head = new HeadModel
                            {
                                text = "审批提醒",
                                bgcolor = "FFBBBBBB"
                            },
                            body = new BodyModel
                            {
                                title = $"审批提醒",
                                content = $"【{applicantName}】有一个新的{adjustName}预约申请需要您审批",
                                form = new List<KeyValue>
                                {
                                   new  KeyValue{

                                        value = flowName,
                                        key = "审批流程："
                                    },
                                    new  KeyValue{
                                        value = content,
                                        key = "详情："
                                    },
                                   new  KeyValue {
                                        value = applicantName,
                                        key = "申请人："
                                    },
                                    new  KeyValue{
                                        value = applyTime,
                                        key = "申请时间："
                                    },
                                   new  KeyValue {
                                        value = "请尽快处理",
                                        key = "备注："
                                    }
                                }
                            }
                        }

                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }
        /// <summary>
        /// 发送取消预约消息
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="title">eg: 自习预约/场地预约</param>
        /// <param name="time">eg: 2020年12月23日 上午十点</param>
        /// <param name="siteName">eg: 泉山17号楼 101</param>
        /// <param name="reason">eg: 与课表安排冲突</param>
        /// <param name="remark">eg: 谢谢您的理解与支持！</param>
        /// <returns></returns>
        public DingTalkSendMsg DingSendCancelOrderMsg(string userid, string title,
            string time, string siteName, string reason, string remark = "谢谢您的理解与支持!")
        {
            try
            {
                string value = string.Empty;
                if (string.IsNullOrEmpty(reason))
                {
                    value = $"您的{title}已被取消";
                }
                else
                {
                    value = $"您的{title}由于{reason}已被取消";
                }
                DingTalkAsyncSend msgRM = new DingTalkAsyncSend
                {
                    to_all_user = false,
                    userid_list = userid,
                    agent_id = _agentId,
                    msg = new MsgModel
                    {
                        msgtype = "oa",
                        oa = new OAModel
                        {
                            message_url = "",
                            head = new HeadModel
                            {
                                text = "预约取消提醒",
                                bgcolor = "FFBBBBBB"
                            },
                            body = new BodyModel
                            {
                                title = $"预约取消提醒",
                                content = value,
                                form = new List<KeyValue>
                                {
                                   new  KeyValue{

                                        value = $"{title}(场地:{siteName})",
                                        key = "预约项目："
                                    },
                                    new  KeyValue{
                                        value = time,
                                        key = "预约时间："
                                    },
                                   new  KeyValue {
                                        value = remark,
                                        key = "备注："
                                    }
                                }
                            }
                        }

                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }

        /// <summary>
        /// 发送取消批量预约消息
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="title">eg: 自习预约/场地预约</param>
        /// <param name="project"></param>
        /// <param name="time">eg: 2020年12月23日 上午十点</param>
        /// <param name="siteName">eg: 泉山17号楼 101</param>
        /// <param name="reason">eg: 与课表安排冲突</param>
        /// <param name="remark">eg: 谢谢您的理解与支持！</param>
        /// <returns></returns>
        public DingTalkSendMsg DingSendCancelBatchOrderMsg(string userid, string title, string project,
            string time, string siteName, string reason, string remark = "谢谢您的理解与支持!")
        {
            try
            {
                string value = string.Empty;
                if (string.IsNullOrEmpty(reason))
                {
                    value = $"您的{title}已被取消";
                }
                else
                {
                    value = $"您的{title}由于{reason}已被取消";
                }
                DingTalkAsyncSend msgRM = new DingTalkAsyncSend
                {
                    to_all_user = false,
                    userid_list = userid,
                    agent_id = _agentId,
                    msg = new MsgModel
                    {
                        msgtype = "oa",
                        oa = new OAModel
                        {
                            message_url = "",
                            head = new HeadModel
                            {
                                text = "预约取消提醒",
                                bgcolor = "FFBBBBBB"
                            },
                            body = new BodyModel
                            {
                                title = $"预约取消提醒",
                                content = value,
                                form = new List<KeyValue>
                                {
                                   new  KeyValue{

                                        value = $"{project}(场地:{siteName})",
                                        key = "详情："
                                    },
                                    new  KeyValue{
                                        value = time,
                                        key = "时间："
                                    },
                                   new  KeyValue {
                                        value = remark,
                                        key = "备注："
                                    }
                                }
                            }
                        }

                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }

        /// <summary>
        /// 发送审批状态提醒
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="flowType">场地/自习</param>
        /// <param name="site">17号楼A101</param>
        /// <param name="time">第八周 星期四 第3节</param>
        /// <param name="res">审批通过/驳回</param>
        /// <returns></returns>
        public DingTalkSendMsg DingSendBookingStatusMsg(string userid, string auditorName,
            string flowType, string site, string time, string res)
        {
            try
            {
                string text = "预约申请通过提醒";
                string firstValue = "您的预约已经审批通过！";
                if (res != "审批通过")
                {
                    text = "预约审批驳回提醒";
                    firstValue = $"您的预约被【{auditorName}】驳回！";
                }
                DingTalkAsyncSend msgRM = new DingTalkAsyncSend
                {
                    to_all_user = false,
                    userid_list = userid,
                    agent_id = _agentId,
                    msg = new MsgModel
                    {
                        msgtype = "oa",
                        oa = new OAModel
                        {
                            message_url = "",
                            head = new HeadModel
                            {
                                text = text,
                                bgcolor = "FFBBBBBB"
                            },
                            body = new BodyModel
                            {
                                title = text,
                                content = firstValue,
                                form = new List<KeyValue>
                                {
                                   new  KeyValue{

                                        value = $"{flowType}订单",
                                        key = "审批项："
                                    },
                                    new  KeyValue{
                                        value = site,
                                        key = "场地："
                                    },
                                    new  KeyValue{
                                        value = time,
                                        key = "时间："
                                    },
                                    new  KeyValue{
                                        value = res,
                                        key = "审批结果："
                                    },
                                   new  KeyValue {
                                        value = "感谢您的使用",
                                        key = "备注："
                                    }
                                }
                            }
                        }

                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }

        /// <summary>
        /// 发送给场地管理员
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="flowType">场地/自习</param>
        /// <param name="site">17号楼A101</param>
        /// <param name="time">第八周 星期四 第3节</param>
        /// <param name="res">审批通过/驳回</param>
        /// <returns></returns>
        public DingTalkSendMsg DingSendToSiteManagerRemind(string userid,string flowType, string site, string time, string res)
        {
            try
            {
                string resStr = res;
                if (res == "取消")
                {
                    resStr = "取消预约";
                }
                if (flowType == "批量场地")
                {
                    flowType = "场地";
                }
                DingTalkAsyncSend msgRM = new DingTalkAsyncSend
                {
                    to_all_user = false,
                    userid_list = userid,
                    agent_id = _agentId,
                    msg = new MsgModel
                    {
                        msgtype = "oa",
                        oa = new OAModel
                        {
                            message_url = "",
                            head = new HeadModel
                            {
                                text = $"您管理的{flowType}[{site}]已被{resStr}",
                                bgcolor = "FFBBBBBB"
                            },
                            body = new BodyModel
                            {
                                title = $"您管理的{flowType}[{site}]已被{resStr}",
                                content = "",
                                form = new List<KeyValue>
                                {
                                   new  KeyValue{

                                        value = time,
                                        key = "时间："
                                    },
                                    new  KeyValue{
                                        value = site,
                                        key = "地点："
                                    },
                                    new  KeyValue{
                                        value = res == "取消" ? "取消":"通过",
                                        key = "预约结果："
                                    },
                                   new  KeyValue {
                                        value = "请您合理安排时间，及时关注使用情况！",
                                        key = "备注："
                                    }
                                }
                            }
                        }

                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }
        /// <summary>
        /// 发送消息提醒
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="orderId"></param>
        /// <param name="res"></param>
        /// <returns></returns>
        public DingTalkSendMsg DingSendMsgRemind(string userid,int orderId, string res)
        {
            try
            {
                var action_url = $"{_clientHost}/details?id={orderId}&type=2";
                if (res.Contains("已评价"))
                {
                    action_url = $"{_clientHost}/evaluation?id={orderId}&type=3";
                }
                string title = res;
                if (res.Length > 10)
                {
                    title = res.Substring(0, 10);
                }
                DingTalkAsyncSend msgRM = new DingTalkAsyncSend
                {
                    to_all_user = false,
                    userid_list = userid,
                    agent_id = _agentId,
                    msg = new MsgModel
                    {
                        msgtype = "action_card",
                        action_card = new ActionCardModel
                        {
                            title = title,
                            markdown = res,
                            single_title = "查看详情",
                            single_url = action_url
                        }

                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }
        public DingTalkSendMsg SendTemplateMsg(DingTalkAsyncSend data)
        {
            try
            {
                string token = DingTalkToken.GetInstance(_appid, _appSecret).AccessToken;
                string url = $"https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token={token}";
                return HTTPHelper.Post<DingTalkSendMsg>(url, data);
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}
